<template>
  <div class="deploy-online">
    <Card :bordered="false">
      <div class="breadcrumb">
        <Breadcrumb>
          <BreadcrumbItem>{{workspaceName}}</BreadcrumbItem>
          <BreadcrumbItem>{{envName}}</BreadcrumbItem>
          <BreadcrumbItem>{{projectName}}</BreadcrumbItem>
        </Breadcrumb>
      </div>
      <Row :gutter="12">
        <Col span="24">
          <Row class="deploy-status">
            <Col span="4">Deploy前置</Col>
            <Col span="4">Deploy部署</Col>
            <Col span="4">Deploy后置</Col>
            <Col span="4">Release前置</Col>
            <Col span="4">Release部署</Col>
            <Col span="4">Release后置</Col>

          </Row>
          <Row class="deploy-status">
            <Col span="24">
              <Progress :percent="percentNumber" :status="progressStatus"/>
            </Col>
          </Row>
          <div class="submit">
            <Button type="primary" class="deploy-task" @click="handleDeployTask" :loading="loading"
                    :disabled="disabled">{{display}}
            </Button>
          </div>
        </Col>
        <Col span="24" v-if="percentNumber">
          <div class="wl-task-log">
            <div class="wl-task-log__body">
              <pre>
                <div class="wl-task-log__line" v-for="item in consoleData">
                  <a/>
                  <span class="error" v-if="item.error">{{item.error}}
                  </span><span class="success" v-else-if="item.success">{{item.success}}</span><span
                  class="command"
                  v-else>[{{item.user}}@{{item.ip}}]$ {{item.command}}</span>
                </div>
              </pre>
            </div>
          </div>
        </Col>
      </Row>
    </Card>
  </div>
</template>

<script>
  import {showTask} from '@/api/task'
  import {getToken} from '@/libs/cookie'
  import Bus from '@/bus'

  export default {
    name: 'online',
    data() {
      return {
        id: '',
        workspaceName: '',
        envName: '',
        projectName: '',
        path: process.env.VUE_APP_WEBSOCKET_API,
        socket: '',
        percentNumber: 0,
        display: '部署',
        progressStatus: 'active',
        loading: false,
        disabled: false,
        consoleData: [],
        //ws
        lockReconnect: false,//是否真正建立连接
        timeout: 28 * 1000,//30秒一次心跳
        timeoutObj: null,//心跳心跳倒计时
        serverTimeoutObj: null,//心跳倒计时
        timeoutNum: null,//断开 重连倒计时
      }
    },
    watch: {
      $route: {
        handler: function () {
          this.id = this.$route.params.id || ''
          this.progressStatus = 'active'
          this.percentNumber = 0
          this.consoleData = []
          this.connect()
        },
      }
    },
    mounted() {
      this.id = this.$route.params.id || ''
      this.handleShowTask(this.id)
      this.connect()
    },
    methods: {
      handleShowTask: function (id) {
        showTask({id: id}).then(res => {
          this.workspaceName = res.data.workspace_name || ''
          this.projectName = res.data.project_name || ''
          this.envName = res.data.env_name || ''
        })
      },
      //部署
      handleDeployTask: function () {
        this.send({cmd: 'deploy', task_id: this.id})
        this.loading = true
        this.percentNumber = 0
        this.consoleData = []
        this.display = '小主请稍等'
      },
      //渲染数据
      handleConsoleData: function (_data) {
        this.percentNumber = _data.percent || 0
        this.consoleData.push({
          'user': _data.user,
          'ip': _data.ip,
          'command': _data.command,
          'error': '',
          'success': '',
        })

        if (_data.status === 0) {
          this.consoleData.push({
            'error': _data.error,
          })
          this.progressStatus = 'wrong'
          this.loading = false
          this.display = '部署'
        } else if (_data.success) {
          this.consoleData.push({
            'success': _data.success,
          })
        }

        if (this.percentNumber === 100) {
          this.disabled = true
          this.display = '部署'
          //刷新列表
          Bus.$emit('handelFlashDeployList')
        }
      },
      //初始化
      connect: function () {
        if (typeof (WebSocket) === 'undefined') {
          this.$Message.error('您的浏览器暂不支持websocket')
        } else {
          // 实例化socket
          this.socket = new WebSocket(this.path + '?access_token=' + getToken() + '&task_id=' + this.id)
          // 监听socket连接
          this.socket.onopen = this.open
          // 监听socket错误信息
          this.socket.onerror = this.error
          // 监听socket消息
          this.socket.onmessage = this.message
        }
      },
      //心跳检测
      start() {
        console.log(`ping:${this._showTime()}`)
        let self = this
        self.timeoutObj && clearTimeout(self.timeoutObj)
        self.serverTimeoutObj && clearTimeout(self.serverTimeoutObj)
        self.timeoutObj = setTimeout(function () {
          //这里发送一个心跳，后端收到后，返回一个心跳消息，
          if (self.socket.readyState === 1) {
            self.send({cmd: 'HeartBeat', task_id: this.id})
          } else {
            self.reconnect()
          }
          //超时关闭
          self.serverTimeoutObj = setTimeout(function () {
            self.close()
          }, self.timeout)
        }, self.timeout)
      },
      //重新连接
      reconnect() {
        let that = this
        if (that.lockReconnect) {
          return
        }
        that.lockReconnect = true
        //没连接上会一直重连，设置延迟避免请求过多
        that.timeoutNum && clearTimeout(that.timeoutNum)
        //新连接
        that.timeoutNum = setTimeout(function () {
          that.connect()
          that.lockReconnect = false
        }, 5000)
      },
      send: function (params) {
        this.socket.send(JSON.stringify(params))
      },
      open: function () {
        console.log('websocket已连接' + this.id)
        this.start()
      },
      error: function () {
        console.log(this.path + '   websocket连接错误')
      },
      message: function (msg) {
        const _data = JSON.parse(msg.data)
        console.log(_data)
        let cmd = _data.cmd
        if (cmd === 'HeartBeatRecv') {
          console.log(`pong: ${this._showTime()}`)
        } else if (cmd === 'info') {
          this.disabled = true
          this.loading = false
          this.display = '部署'
          this.$Message.error(_data.data)
        } else {
          this.handleConsoleData(_data.data)
        }
      },
      close: function () {
        this.start()
      },
      _showTime: function () {
        let date = new Date()
        let seperator1 = '-'
        let seperator2 = ':'
        let month = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1
        let strDate = date.getDate() < 10 ? '0' + date.getDate() : date.getDate()
        return date.getFullYear() + seperator1 + month + seperator1 + strDate
          + ' ' + date.getHours() + seperator2 + date.getMinutes()
          + seperator2 + date.getSeconds()
      }
    },
  }
</script>

<style scoped lang="less">
  @import "./index.less";
</style>
